#include "../sleipner_config.h"
#include "ogl_graphics.h"

#include "ogl_font.h"
#include "ogl_image_cache.h"
#include "ogl_buffer.h"

#include "ogl_surface.h"
#include "ogl_dynamic_image.h"

#include "util/mmgr.h"	
#include "util/common_macros.h"		// macros
#include "application/game_application.h"
#include "util/timer.h"				// log
#include "util/log.h"				// log

#ifdef _PLATFORM_WIN32
#include "gameswf/gameswf.h"
#endif

extern "C"
{
#ifdef _SDL2
    
#include "SDL2/include/SDL.h"
    #ifdef _PLATFORM_WIN32
        #include "glee/glee.h"
    //#include "SDL-1.2.13/include/SDL_opengl.h"
    #else
        #ifdef _OPENGLES2
            #include "SDL2/include/SDL_opengles2.h"
        #else
            #include "SDL2/include/SDL_opengles.h"
        #endif
    #endif
    
#else
    
    
    #include "SDL-1.2.13/include/SDL.h"
    #ifndef _PLATFORM_IOS
        #include "glee/glee.h"
		
        //#include "SDL-1.2.13/include/SDL_opengl.h"
    #else
        #include "SDL-1.2.13/include/SDL_opengles.h"
    #endif

#endif
    
}

#include <cassert>

#ifdef _PLATFORM_WIN32
gameswf::render_handler*  create_render_handler_ogl(void);
#endif

extern GameApp*	g_pApp;



OglGraphics*	GetOGLGraphics()
{
	return (OglGraphics*)GetGraphics();
}	

void		OglGraphics::Create()
{
	if (!s_pGraphics)
	{
		s_pGraphics = new OglGraphics();
		// force images to register
		OglSurface::RegisterFormats(); 
	}
}

void		SLEIPNER_CREATE_OGL()
{
	OglGraphics::Create();
}



ImageCache*		OglGraphics::CreateCache(int Width, int Height, int Depth)
{
	OglImageCache* pCache = new OglImageCache();
	pCache->Create(Width, Height, Depth);
	return pCache;	
    
	//return NULL;
}


void		OglGraphics::Delete()
{
	
}


OglGraphics::OglGraphics() : Graphics()	
{
#ifdef _OPENGLES2
	m_EGLProgram = 0;
#endif

	SetGraphicsClass(GRAPHICS_CLASS_OGL);
}

OglGraphics::~OglGraphics()
{	
}

void	OglGraphics::Start2D()
{
	
	//pDevice->SetRenderState( D3DRS_WRAP0, 0 );
	//pDevice->SetRenderState( D3DRS_WRAP1, 0 );
	//pDevice->SetRenderState( D3DRS_WRAP2, 0 );
	//pDevice->SetRenderState( D3DRS_WRAP3, 0 );
    
    //pDevice->SetRenderState( D3DRS_SRCBLEND,            D3DBLEND_SRCALPHA );
	//glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA);
    //pDevice->SetRenderState( D3DRS_DESTBLEND,           D3DBLEND_INVSRCALPHA );
	//glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glFinish();
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    
}


void	OglGraphics::SetFilter2D(bool b)
{
	//if (m_Filter2D == b)
	//	return;
	//Graphics::SetFilter2D(b);
    
	//if (m_Filter2D)
	//{		
    
	//	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	//	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    
	//} else
	//{
	//	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
	//	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
	//}
}

bool	OglGraphics::ResetWindow(unsigned int Width, unsigned int Height, bool Fullscreen)
{
    
	return true;
}


#ifdef _SDL2

#else

bool	OglGraphics::InitWindow(unsigned int Width, unsigned int Height, bool Fullscreen, bool EnableDebug)
{
    m_IsWindowed					 = !Fullscreen;
	m_IsWindowed					 = true;
	
	Uint32 Flag = SDL_OPENGL;
    
    
#if defined( _PLATFORM_IOS) || defined( _PLATFORM_ANDROID)
#else   
	if(!m_IsWindowed)
#endif
    {
		Flag = Flag |SDL_FULLSCREEN;
        
#if defined( _PLATFORM_IOS) || defined( _PLATFORM_ANDROID)
		//Flag = Flag | SDL_WINDOW_BORDERLESS;
        Flag = Flag | SDL_WINDOW_RESIZABLE;
       // Flag = Flag | SDL_NOFRAME;
#endif
        
    }

	SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    
	putenv(strdup("SDL_VIDEO_CENTERED=1")); 
	if ( SDL_SetVideoMode( Width, Height, 32, Flag ) == NULL )
	{
		return false;
	}    
     
	const SDL_VideoInfo *pInfo = SDL_GetVideoInfo();
    if(pInfo)
    {
    	Width = pInfo->current_w;
    	Height = pInfo->current_h;

    	_LOG(MSG_INIT, "Width: " << Width );
    	_LOG(MSG_INIT, "Height " << Height );
    }
    else
    {

    	_LOG(MSG_ERROR, "SDL_GetVideoInfo Fail " << SDL_GetError() );
    }


    m_ScreenWidth  = Width;
	m_ScreenHeight = Height;
    

	math::Viewport Vp;
	Vp.Width = Width;
	Vp.Height = Height;
	SetViewport(Vp);
	
    
    
//#ifndef _PLATFORM_IOS       // ios use lauch image already, we dun need black screen at the very start
    glClearColor(0,0,0,1);	
	glClear(GL_COLOR_BUFFER_BIT );
	Uint32 Black = SDL_MapRGB(SDL_GetVideoSurface()->format, 0, 0, 0);
	SDL_FillRect(SDL_GetVideoSurface() , NULL, Black );			// be nice and show black screen
	SDL_GL_SwapBuffers();	// be nice and show black screen
    glClearColor(0,0,0,1);	
	glClear(GL_COLOR_BUFFER_BIT );
    
//#endif
    
	_LOG(MSG_COMMENT ,"VENDOR: "     << (char*)glGetString( GL_VENDOR ));
	_LOG(MSG_COMMENT ,"RENDERER: "   << (char*)glGetString( GL_RENDERER ));
	_LOG(MSG_COMMENT ,"VERSION: "    << (char*)glGetString( GL_VERSION ));
    
    //SDL_free(SDLRect);
    
	return true;
}

void	OglGraphics::EndScene()
{
	SDL_GL_SwapBuffers();
	m_FrameID++;
}

bool	OglGraphics::Shutdown()
{
	return true;
}

#endif   // SDL2

bool	OglGraphics::Init()
{
	if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) 
	{
		return false;
	}
    
	SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
	SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
	SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
    SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );    
	SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 0 );    
	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
    
#if SDL_VERSION_ATLEAST(1,3,0) 
    SDL_GL_SetSwapInterval(1); 
	SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING,1);   // recommended by SDL Readme file ( if redraw every frame completely )
#else /* SDL_VERSION_ATLEAST(1,3,0) */ 
#ifdef SDL_GL_SWAP_CONTROL 
    SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); 
#else /* SDL_GL_SWAP_CONTROL */ 
    //DEBUG("VSync unsupported on old SDL versions (before 1.2.10)."); 
#endif /* SDL_GL_SWAP_CONTROL */ 
#endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    
    
   
    glDisable(GL_DITHER);
    
	//pDevice->SetRenderState( D3DRS_LIGHTING,            FALSE);		
	
    
	//pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE,    TRUE );
	glEnable(GL_BLEND);
    
#ifdef _OPENGLES2
	//glDisable(GL_TEXTURE_GEN_Q);
	//glDisable(GL_TEXTURE_GEN_R);
	//glDisable(GL_TEXTURE_GEN_T);
	//glDisable(GL_TEXTURE_GEN_S);
#else
    
#endif
    
    
	
    
    
    //pDevice->SetRenderState( D3DRS_ALPHATESTENABLE,     TRUE );
    //glEnable(GL_ALPHA_TEST);
    
    //pDevice->SetRenderState( D3DRS_ALPHAREF,            0x10 );
    //pDevice->SetRenderState( D3DRS_ALPHAFUNC,           D3DCMP_GREATER );
       
    //pDevice->SetRenderState( D3DRS_FILLMODE,            D3DFILL_SOLID );
#ifdef _PLATFORM_WIN32
	glPolygonMode(GL_FRONT_AND_BACK , GL_FILL);
#else
    //GL_FILL is not availible , what should i do here?
    //glPolygonMode(GL_FRONT_AND_BACK , GL_FILL);
#endif
    
    
	//pDevice->SetRenderState( D3DRS_CULLMODE,            D3DCULL_CCW );
	glCullFace(GL_FRONT);
    
	//pDevice->SetRenderState( D3DRS_ZENABLE,             FALSE);
	//pDevice->SetRenderState( D3DRS_ZVISIBLE,			FALSE);
    //pDevice->SetRenderState( D3DRS_ZWRITEENABLE,        FALSE);
	glDisable(GL_DEPTH_TEST);
    
	//pDevice->SetRenderState( D3DRS_STENCILENABLE,       FALSE );
	glDisable( GL_STENCIL_TEST);
    
    //pDevice->SetRenderState( D3DRS_FOGENABLE,           FALSE );
	
#ifdef _SDL2
    // using opengel es 2
#else
    
    glDisable(GL_FOG);
    glAlphaFunc(GL_GREATER ,  0.1f );
    glDisable(GL_LIGHTING);
    glEnableClientState( GL_VERTEX_ARRAY );
#endif
	
	return true;
    
}

bool	OglGraphics::ShutdownWindow()
{
	return true;
}




bool	OglGraphics::Resize(unsigned int Width, unsigned int Height)
{
	return Graphics::Resize(Width, Height);
}


void	OglGraphics::SetTexStage(unsigned int TexStage, STAGE_TYPE type, BLEND_OP Op)
{
	//CHIT: reference link
	//http://ttoprpg.com/articles/multitexturing.htm
    
	if(m_pCurTexture[TexStage] == NULL)
		return;
    
	//while(glGetError() != GL_NO_ERROR);		// clear previous errors
    
	if (TexStage < 2)
	{
		assert(type <= Graphics::STAGE_TYPE_COUNT);
        
		if (m_CurTextureStates[TexStage][type] == Op)
			return;
        
		m_CurTextureStates[TexStage][type] = Op;
	}
    
	
	//switch (type)
	//{
    /*case COLOR_ARG1:	
     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, Target); 
     Oprand			    = GL_OPERAND0_RGB_ARB; 	
     break;
     case COLOR_ARG2:	
     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, Target); 
     Oprand			    = GL_OPERAND1_RGB_ARB; 			
     break;
     case ALPHA_ARG1:	
     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA,   Target); 
     Oprand			    = GL_OPERAND0_ALPHA_ARB;
     break;
     case ALPHA_ARG2:	
     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA,   Target); 
     Oprand			    = GL_OPERAND1_ALPHA_ARB; 	
     break;*/
    //case COLOR_OP:		break;		
    //case ALPHA_OP:		break;
    //case MIP_FILTER:    return;
    
	//}
    
#ifdef _SDL2
#else
    
	switch (Op)
	{
		case BLEND_MODULATE:
			glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);	// reset multitexturing
            break;			
			
            ////case BLEND_ADD:			
            ////	glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
            ////	glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,  GL_ADD); 	
            ////	break;
            ////case BLEND_SELECTARG1:	
            ////	glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);	// CHIT:D3DTA_SELECTARG1 
            ////	glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,  GL_REPLACE); 	
            ////break;						
            ////case BLEND_SELECTARG2:	
            ////	glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);	
            ////	glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,  GL_DECAL); 	
            ////break;								
            //////case BLEND_DISABLE:	    
            ////	//glDisable(GL_BLEND);
            //////	break;
		case BLEND_TEXTUREALPHA:										 // Arg1 x Alpha + Arg2 x ( 1 - Alpha )
            
#ifndef _PLATFORM_IOS
			glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);	
			glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,  GL_REPLACE); 
#else
 			glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_COMBINE_RGB);	
			glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,  GL_REPLACE);                
#endif
            break;
            

			
            //case SV_DIFFUSE:		
            //							
            
	}
    
#endif   // SDL2
    
    
    
	//GLenum  ErrCode = glGetError();
	//if (ErrCode != GL_NO_ERROR)    			
	//	bool testbreak = true;			
	
   	
}

void	OglGraphics::SetTexture(unsigned int Stage, Image* pImg) 
{
	if (pImg)
		pImg->SetTextureStage(Stage);
	else
		glBindTexture(GL_TEXTURE_2D ,0);
	
	if (Stage < 2)
		m_pCurTexture[Stage] = pImg;
}



void	OglGraphics::SetRenderState(RENDER_STATE r, unsigned int val)
{
	assert (r <= Graphics::RENDER_STATE_C);
	if (m_CurRenderStates[r] == val)
		return;
	else
		m_CurRenderStates[r] = val;
    
	GLenum Value;
	bool MappingOK     = true;
    
	switch (r)
	{		
		case RS_ALPHA:
			Value = GL_BLEND;
			break;
			
#ifdef _SDL2
    // using opengl es 2
#else
		case RS_ALPHA_TEST:
			Value = GL_ALPHA_TEST;
			break;
        case RS_LIGHTING:
			Value = GL_LIGHTING;
			break;
#endif
		case RS_ALPHA_REF:
			MappingOK = false;
			break;
		
		case RS_ZWRITE:
			glDepthMask(val==0?false:true);	
			MappingOK = false;
			break;
		case RS_ZREAD:
			Value = GL_DEPTH_TEST; 
			break;
		default:
			MappingOK = false;
	}
    
	if(MappingOK)
    {
		if(val == 1)
			glEnable(Value);
		else
			glDisable(Value);		
	}
    
	if(r == RS_DST_BLEND) //CHIT: we only excute when two parameter have been passed
	{
		GLenum SourceValue = GL_SRC_ALPHA;
		GLenum DestValue   = GL_ONE_MINUS_SRC_ALPHA;
        MappingOK     = true;
		
		unsigned int CheckVal = 0;
        
		for(int i = 0; i <2; i++)
		{
			if( i ==0 )
				CheckVal = m_CurRenderStates[RS_SRC_BLEND];
			else
				CheckVal = val;
            
			switch (CheckVal)
			{
				case RV_BLEND_ONE: Value = GL_ONE; break;
				case RV_BLEND_ZERO: Value = GL_ZERO; break;
				case RV_BLEND_SRC: Value = GL_SRC_COLOR; break;
				case RV_BLEND_INVSRC: Value = GL_ONE_MINUS_SRC_COLOR; break;
				case RV_BLEND_SRC_ALPHA: Value = GL_SRC_ALPHA; break;
				case RV_BLEND_INVSRC_ALPHA: Value = GL_ONE_MINUS_SRC_ALPHA; break;
                    
				case RV_BLEND_DEST: Value = GL_DST_COLOR; break;
				case RV_BLEND_INVDEST: Value = GL_ONE_MINUS_DST_COLOR; break;
                    
				case RV_BLEND_DEST_ALPHA: Value = GL_DST_ALPHA; break;
				case RV_BLEND_INVDEST_ALPHA: 
					MappingOK = false;
					break;
                    
				default:
					MappingOK = false;
			}
            
			if(MappingOK)
            {
				if( i ==0 )
					SourceValue = Value;
				else
                    DestValue   = Value;
            }
            
		}		// for end
        
		glBlendFunc(SourceValue,DestValue);		
        
	}
    
	if(r == RS_CULL_MODE)
	{
		switch (val)
		{
            case RV_CULL_NONE:	
#if !defined(_PLATFORM_ANDROID) &&  !defined(_PLATFORM_IOS)
                glCullFace(GL_NONE);
#else
                glCullFace(0x0);
#endif
                
                break;
            case RV_CULL_CW:	
                glCullFace(GL_FRONT);break;
            case RV_CULL_CCW: 
            default:		
                glCullFace(GL_BACK);break;			
		}
	}
    
	//GLenum  ErrCode = glGetError();
	//if (ErrCode != GL_NO_ERROR)    
	//	bool testbreak = true;
	
	return;
	
}


void	OglGraphics::SetTransform(TRANSFORM_STAGE ts, const math::Mat4x4& mat)
{
	
}

void	OglGraphics::SetViewport(const math::Viewport& vp)
{
	glViewport(0,0,vp.Width,vp.Height);
    

#ifdef _OPENGLES2
    // using open gl es 2
#else
    
    glMatrixMode(GL_PROJECTION);
#if !defined(_PLATFORM_ANDROID) &&  !defined(_PLATFORM_IOS)
        glOrtho(0, vp.Width ,vp.Height,0 , -1, 1);
    #else
        glOrthof(0, vp.Width ,vp.Height,0 , -1, 1);
    
    #endif
    
    glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
    
#endif
	
}

bool	OglGraphics::BeginScene()
{
	// reset our debug counters here
	m_PolygonC= 0;
	m_BatchC=0;
	return true;
}

void	OglGraphics::Clear(COLOR c, 
                           float Depth, 
                           int Stencil , 
                           bool ClearRGB , 
                           bool ClearDepth,
                           bool ClearStencil)
{
	if(m_pForceTexture)
		glClearColor(0,0,0,1);
	else
	{
		if(ClearRGB)
			glClearColor(ColorGetRf(c),ColorGetGf(c),ColorGetBf(c),ColorGetAf(c));
        
	}
    
#ifdef _PLATFORM_WIN32
	if(ClearDepth)
		glClearDepth (Depth);
	 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
#else
    //if(ClearDepth)
	//	glClearDepthf(Depth);
    glClear(GL_COLOR_BUFFER_BIT );
#endif
    

    
    if(ClearStencil)
    	glClearStencil (Stencil);
}




bool OglGraphics::Present()
{
	return true;
}

#ifdef _OPENGLES2
    // the functions are inside ogl_graphics_opengles2

#else

void	OglGraphics::DrawVertex2D(Vertex2D*	VertA, unsigned int VertC, PRIMITIVE_TYPE Type )
{	
	GLenum GLMode;
	unsigned int PrimitiveC = 0;
	MapPrimitiveToOGL(Type,GLMode,VertC,PrimitiveC);
    
	/*
     //Enable this block to use DrawElements	
     glEnableClientState( GL_VERTEX_ARRAY );
     //glEnableClientState( GL_INDEX_ARRAY );
     glEnableClientState( GL_TEXTURE_COORD_ARRAY );
     glEnableClientState( GL_COLOR_ARRAY );
     
     oglVertexBuffer* pBuffer = GetTempVB(VertC);
     pBuffer->Load(VertA,VertC);
     glBindBuffer(GL_ARRAY_BUFFER, pBuffer->GetBuffer());	
     glVertexPointer(2, GL_FLOAT,  sizeof(Vertex2D), (void*)offsetof(Vertex2D,x));	
     glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(Vertex2D) , (void*)offsetof(Vertex2D,color)); 
     glTexCoordPointer(2,GL_FLOAT, sizeof(Vertex2D), (void*)offsetof(Vertex2D,u));	
     
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, GetTempIB(VertC)->GetBuffer());
     
     
     
     glDrawElements(	 
     GL_TRIANGLES, 
     VertC, 
     GL_UNSIGNED_BYTE, 
     (void*)0
     );
     
     glDisableClientState( GL_VERTEX_ARRAY );
     //glDisableClientState( GL_INDEX_ARRAY );
     glDisableClientState( GL_TEXTURE_COORD_ARRAY );
     glDisableClientState( GL_COLOR_ARRAY );
     */
	
	
	// Enable this block to use Vertex Array
    
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_VERTEX_ARRAY);
    
	glVertexPointer(2, GL_FLOAT,  sizeof(Vertex2D), VertA);
	glTexCoordPointer(2,GL_FLOAT, sizeof(Vertex2D), &VertA->u);	
	glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(Vertex2D) , &VertA->color); 
    
	glDrawArrays(GLMode,0,VertC);
    
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);
    
    glDisable(GL_TEXTURE_2D);
	
    
	/*
     // debugging purpose block
     
     bool TextureEnable = glIsEnabled(GL_TEXTURE_2D);
     glDisable(GL_TEXTURE_2D); 
     glBegin(GL_LINES);
     for (unsigned int i=0; i<PrimitiveC; i++)
     {
     int	BaseIndex = (i*3);
     Vertex2D*	pA = &VertA[BaseIndex+0];
     Vertex2D*	pB = &VertA[BaseIndex+1];
     Vertex2D*	pC = &VertA[BaseIndex+2];
     
     glColor4ubv((GLubyte*)&pA->color);
     
     glVertex2f(pA->x,pA->y); 
     glVertex2f(pB->x,pB->y); 
     
     glVertex2f(pB->x,pB->y); 
     glVertex2f(pC->x,pC->y); 
     
     glVertex2f(pC->x,pC->y); 
     glVertex2f(pA->x,pA->y); 
     
     }
     glEnd();
     if(TextureEnable)
     glEnable(GL_TEXTURE_2D);
     */
	
}

void	OglGraphics::DrawIndexVertex2D(Vertex2D*	VertA, unsigned int VertC, unsigned short* IndexA, unsigned int IndexC, PRIMITIVE_TYPE Type)
{
	GLenum GLMode;
	unsigned int PrimitiveC = 0;
	MapPrimitiveToOGL(Type,GLMode,IndexC,PrimitiveC);
	if(GLMode == GL_TRIANGLES)
	{
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_VERTEX_ARRAY);
        
		//glVertexPointer(2, GL_FLOAT,  sizeof(Vertex2D), VertA);
		glTexCoordPointer(2,GL_FLOAT, sizeof(Vertex2D), &VertA->u);	
		glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(Vertex2D) , &VertA->color); 
		//glInterleavedArrays(GL_T2F_C4UB_V3F,sizeof(Vertex2D),VertA);
		
		glDrawElements(GL_TRIANGLES, IndexC , GL_UNSIGNED_SHORT, IndexA);
		//glDrawArrays(GLMode,0,VertC);
        
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
		glDisableClientState(GL_VERTEX_ARRAY);
        
		/*glDisable(GL_TEXTURE_2D); 
         glBegin(GL_LINES);
         for (unsigned int i=0; i<VertC/3; i++)
         {
         int	BaseIndex = (i*3);
         Vertex2D*	pA = &VertA[BaseIndex+0];
         Vertex2D*	pB = &VertA[BaseIndex+1];
         Vertex2D*	pC = &VertA[BaseIndex+2];
         
         glColor4ubv((GLubyte*)&pA->color); 
         
         glVertex2f(pA->x, pA->y); 
         glVertex2f(pB->x, pB->y); 
         
         glVertex2f(pB->x, pB->y); 
         glVertex2f(pC->x, pC->y); 
         
         glVertex2f(pC->x, pC->y); 
         glVertex2f(pA->x, pA->y); 		
         
         }
         glEnd();
         glEnable(GL_TEXTURE_2D);*/
        
	}
    
    
}

#endif  // SDL2

Font*	OglGraphics::CreateTTFFont(const std::string& Name)
{
	return new oglFont(Name);
	//return NULL;
}

AVI*	OglGraphics::LoadMovie(const std::string& Name)
{
	
	return NULL;
}

void	OglGraphics::DestroyMovie(AVI* pAVI)
{
	
}


Image*	OglGraphics::LoadImageFromFile(const std::string& Format)
{
	
    if (Format.empty())
	{
        _LOG(MSG_WARNING, "Trying to load texture, but no file-name given");
		return NULL;
	}
	if (Format.size() < 4)
    {
        _LOG(MSG_WARNING, "Unable to find the file-type of image file " << Format);
        return NULL;
    }
    
	const char*     File    = Format.c_str();
	size_t          SL      = strlen(File);
	char	        Ext[]   = {
        static_cast<char>(tolower(File[SL-3])),
        static_cast<char>(tolower(File[SL-2])),
        static_cast<char>(tolower(File[SL-1])),
        '\0'};
    
    if (File[SL-4] != '.')  // all internal file formats are 3 lettered extensions
    {
		
        _LOG(MSG_WARNING, "Unable to find the file-type of image file " << Format);
        return NULL;
    }
    Image* pImg = NULL;
    
	if (strcmp(Ext, "jpg")==0) pImg = new Image(); 
	else if (strcmp(Ext, "png")==0) pImg = new Image();
    
    if (pImg)
    {
        if (!pImg->Load(Format))
        {
            UTIL_SAFE_DELETE(pImg);
        }
    }
    return pImg;
	//return NULL;
}
Image*	OglGraphics::LoadImageFromMemory(unsigned char* pData, unsigned int	Size)
{
    
	return NULL;
}



Image*	OglGraphics::CreateDynamicImage(unsigned short Width, unsigned short Height, unsigned short Depth)
{
	return NULL;	
}

Image*	OglGraphics::CreateComposite(int	width, int height, int depth, const std::vector<ImageLayer>& Layers)
{
	
	return NULL;
}

void	OglGraphics::RegisterFormats()
{
	OglSurface::RegisterFormats();
}

void	OglGraphics::GetBestWideScreenRes(unsigned int& aWidth, unsigned int& aHeight, bool bGetForBackbuffer)
{
    
}




bool	OglGraphics::MapPrimitiveToOGL(PRIMITIVE_TYPE Type, GLenum& GLMode , unsigned int VertC, unsigned int& PrimitiveC)
{
    
	switch (Type)
	{
		case PT_POINT_LIST:
			GLMode = GL_POINTS;
			PrimitiveC = VertC;
            break;
            
		case PT_LINE_LIST:
			GLMode = GL_LINES;
			PrimitiveC = VertC/2;
            break;
            
		case PT_LINE_STRIP:
			GLMode = GL_LINE_STRIP;
			PrimitiveC = VertC-1;
            break;
            
		case PT_TRI_STRIP:
			GLMode = GL_TRIANGLE_STRIP;
			PrimitiveC = VertC-2;
            break;
            
		case PT_TRI_FAN:
			GLMode = GL_TRIANGLE_FAN;
			PrimitiveC = VertC-1;
            break;
            
		case PT_TRI_LIST:	// default case
			GLMode = GL_TRIANGLES;
			PrimitiveC = VertC/3;
            break;
            
		default:
			PrimitiveC = 0;
			return false;
            break;
	}
    
	return true;
    
}

void*	OglGraphics::GetFlashDriver()
{
	//return gameswf::create_render_handler_ogl(); 
	return NULL;
}


oglVertexBuffer*		OglGraphics::GetTempVB(int VertC)
{
   	if (m_VBSets.empty())
	{
		// lazy generation
		m_VBSets.push_back(new oglVBSet(30, 32, sizeof(Vertex2D), 0));
		m_VBSets.push_back(new oglVBSet(10, 128, sizeof(Vertex2D), 0));
		m_VBSets.push_back(new oglVBSet(5,  1024, sizeof(Vertex2D), 0));
		m_VBSets.push_back(new oglVBSet(2,  1024 * 64, sizeof(Vertex2D), 0));
	}
	for (unsigned int i=0; i<m_VBSets.size(); i++)
	{
		if (m_VBSets[i]->CanFit(VertC)) return (oglVertexBuffer*)m_VBSets[i]->GetBuffer();
	}
	return 0;
}

oglIndexBuffer*	OglGraphics::GetTempIB(int IndexC)
{
	if (m_IBSets.empty())
	{
		// lazy generation
		m_IBSets.push_back(new oglIBSet(30, 32));
		m_IBSets.push_back(new oglIBSet(5, 1024));
		m_IBSets.push_back(new oglIBSet(5, 1024*64));
	}
	for (unsigned int i=0; i<m_IBSets.size(); i++)
	{
		if (m_IBSets[i]->CanFit(IndexC)) return (oglIndexBuffer*)m_IBSets[i]->GetBuffer();
	}
	return 0;
}







